package com.itheima.j2cache.aop.processor;

import com.itheima.j2cache.anno.Cache;
import com.itheima.j2cache.anno.CacheEvictor;
import com.itheima.j2cache.model.AnnotationInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 清理缓存注解处理器
 *
 * @author llhuang10
 * @date 2021/10/8 9:48
 */
@Slf4j
public class CacheEvictorAnnotationProcessor extends AbstractCacheAnnotationProcessor {


    private List<AnnotationInfo<Cache>> cacheList = new ArrayList<>();

    /**
     * 初始化清理缓存注解处理器低下, 同时初始化一些缓存操作的对象
     *
     * @param joinPoint  切点
     * @param annotation 注解
     */
    public CacheEvictorAnnotationProcessor(ProceedingJoinPoint joinPoint, Annotation annotation) {
        super();
        CacheEvictor cacheEvictor = (CacheEvictor) annotation;
        Cache[] value = cacheEvictor.value();
        Arrays.stream(value).forEach(cache -> {
                    AnnotationInfo<Cache> annotationInfo = super.getAnnotationInfo(joinPoint, cache);
                    cacheList.add(annotationInfo);
                }
        );
    }

    /**
     * 具体清理缓存的处理逻辑
     *
     * @param joinPoint 切点
     * @return joinPoint.proceed()
     */
    @Override
    public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
        cacheList.forEach(
                annotationInfo -> {
                    String region = annotationInfo.getRegion();
                    String key = annotationInfo.getKey();
                    String params = annotationInfo.getAnnotation().params();
                    String classMethodName = this.getKey(joinPoint);
                    if (classMethodName.equals(key) && "".equals(params)) {
                        // key为className:methodName, 就表示 @Cache中的key为缺省值, controller中key没有填写, param也没有填写, 就表示清空rg区域的缓存
                        // 清理指定region的所有缓存数据
                        cacheChannel.clear(region);
                    } else {
                        // 清理指定region中key的缓存数据
                        cacheChannel.evict(region, key);
                    }
                }
        );

        // 放行目标方法controller [joinPoint.process()]  --> controller方法还会执行从DB删除数据操作
        return joinPoint.proceed(joinPoint.getArgs());
    }


    /**
     * 动态获取目标controller方法的类名和方法名拼接结果  如 J2CacheController:clearAll
     *
     * @param joinPoint 切点
     * @return className:methodName
     */
    private String getKey(ProceedingJoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String methodName = methodSignature.getMethod().getName();
        return className + ":" + methodName;
    }

}
